﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ServiceModel.DomainServices.Server;
using Agility.Web.Repositories;

namespace Agility.Web.Services.RepositoryDomainServicePattern
{
    public class RepositoryDomainService : DomainService
    {
        private readonly Dictionary<Type, IRepository> repositories = new Dictionary<Type, IRepository>();

        protected RepositoryDomainService(IRepository repository)
        {
            this.AddRepository(repository);
        }
        
        protected RepositoryDomainService(IList<IRepository> repositories)
        {
            foreach (IRepository repository in repositories)
            {
                this.AddRepository(repository);
            }
        }

        //protected IUnitOfWork UnitOfWork { get { return this.unitOfWork; } }

        protected override int Count<T>(IQueryable<T> query)
        {
            return query.Count();
        }

        protected override bool PersistChangeSet()
        {
            foreach (ChangeSetEntry cse in this.ChangeSet.ChangeSetEntries)
            {
                IRepository repo = this.GetRepository(cse.Entity.GetType());
                if (repo != null)
                    repo.Save();
            }
            return true;
        }

        protected IRepository GetRepository(Type type)
        {
            if (this.repositories.ContainsKey(type))
                return this.repositories[type];
            return null;
        }

        protected void SetRepository(Type type, IRepository repository)
        {
            if (repository == null)
                this.repositories.Remove(type);
            else
                this.repositories[type] = repository;
        }

        private void AddRepository(IRepository repository)
        {
            Type repositoryInterface = repository.GetType().GetInterface("IRepository`1");
            if (repositoryInterface == null)
                throw new ArgumentException("The repository does not implement IRepository<T>", "repository");
            Type entityType = repositoryInterface.GetGenericArguments().Single();
            this.SetRepository(entityType, repository);
        }

        protected void InsertEntity(object entity)
        {
            this.GetRepository(entity.GetType()).Insert(entity);
        }

        protected void UpdateEntity(object entity)
        {
            this.GetRepository(entity.GetType()).Update(entity, this.ChangeSet.GetOriginal(entity));
        }

        protected void DeleteEntity(object entity)
        {
            this.GetRepository(entity.GetType()).Delete(entity);
        }
    }
}